#include "wc3_native_signature_parser.h"
#include "Extern_global_Variable.h"

typedef Dword TParserState;

	enum TParserState_Enum {
		psWaitingForArgumentsStart,
		psParsingArguments,
		psParsedArgument,
		psParsingType,
		psParsingSubTypeName,
		psParsingReturnType,
		psParsedReturnType,
		psFinished
	};

Boolean NextChar(String Text, Integer &Position, Char &c)
{
	Boolean Result;
	Result = FALSE;

	if ((Position >= 1) && (Position <= strlen(Text)))
	{
		c = Text[Position];
		Position++;
		Result = TRUE;
	};
	return Result;
};

Boolean ParseNativeFunctionSignature(
	String Signature,
	TNativeFunctionSignature &ParsedSignature,
	Boolean CheckFinished
)
{
	Integer vvi;
	Boolean Result;
	TParserState State = psWaitingForArgumentsStart;
	TParserState StateToEnterAfterWorkDone;
	Integer Position = 1;
	Char CurrentChar;
	TNativeFunctionArgumentType CurrentType;
	char SubTypeNameBuilder[100];

	Result = FALSE;

	StateToEnterAfterWorkDone = psFinished;
	ParsedSignature.Arguments = NULL;
	CurrentChar = '?';
	CurrentType.TypeId = '?';
	CurrentType.SubTypeName = "";

	memset(SubTypeNameBuilder,0,sizeof(SubTypeNameBuilder));
	vvi = 0;

	while (TRUE)
	{
		switch (State)
		{
			case psWaitingForArgumentsStart:
			{
				if (!NextChar(Signature, Position, CurrentChar))
					goto m1;

				if (CurrentChar == '(')
				{
					State = psParsingArguments;
				}
				else
				{
					goto m1;
				}
			};
			break;

			case psParsingArguments:
			{
				if (!NextChar(Signature, Position, CurrentChar))
					goto m1;

				if (CurrentChar == ')')
				{
					State = psParsingReturnType;
				}
				else
				{
					Position--; // put type letter back
					State = psParsingType;
					StateToEnterAfterWorkDone = psParsedArgument;
				};
			};
			break;

			case psParsedArgument:
			{
					ParsedSignature.Arguments = new TNativeFunctionArgumentType[sizeof(*ParsedSignature.Arguments)/sizeof(ParsedSignature.Arguments[0])+1];
					ParsedSignature.Arguments[sizeof(*ParsedSignature.Arguments)/sizeof(ParsedSignature.Arguments[0]) - 1] = CurrentType;

				State = psParsingArguments;
			};
			break;

			case psParsingType:
			{
				if (!NextChar(Signature, Position, CurrentChar))
					goto m1;

				CurrentType.TypeId = CurrentChar;
				CurrentType.SubTypeName = "";

				if (CurrentChar == 'H')
				{
					memset(SubTypeNameBuilder,0,sizeof(SubTypeNameBuilder));
					vvi = 0;
					State = psParsingSubTypeName;
					StateToEnterAfterWorkDone = StateToEnterAfterWorkDone;
				}
				else
					State = StateToEnterAfterWorkDone;
			};
			break;

			case psParsingSubTypeName:
			{
				if (!NextChar(Signature, Position, CurrentChar))
					goto m1;

				if (CurrentChar == ';')
				{
					CurrentType.SubTypeName = new char[strlen(SubTypeNameBuilder)+1];
					sprintf(CurrentType.SubTypeName,"%s\0",SubTypeNameBuilder);
					State = StateToEnterAfterWorkDone;
				}
				else
				{
					SubTypeNameBuilder[vvi] = CurrentChar;
					vvi++;
				}
			};
			break;

			case psParsingReturnType:
			{
				State = psParsingType;
				StateToEnterAfterWorkDone = psParsedReturnType;
			};
			break;

			case psParsedReturnType:
			{
				ParsedSignature.ReturnType = CurrentType;
				State = psFinished;
			};
			break;

			case psFinished:
			{
				if (CheckFinished)
				{
					Result = Position > strlen(Signature);
				}
				else
				{
					Result = TRUE;
				}

				goto m1;
			};
		};
	};
m1:
	return Result;
};
